package org.martin.snsrs.crawler;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javassist.expr.NewArray;

import org.apache.commons.collections.map.StaticBucketMap;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.hql.ast.tree.IntoClause;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.martin.snsrs.crawler.database.Activity;
import org.martin.snsrs.crawler.database.ActivitiesDAO;
import org.martin.snsrs.crawler.database.ActivityTags;
import org.martin.snsrs.crawler.database.ActivityTagsDAO;
import org.martin.snsrs.crawler.database.Tags;
import org.martin.snsrs.crawler.database.TagsDAO;

import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;

public class HTMLInfoExtractor {

	private HtmlCleaner cleaner;

	private TagNode rootNode;

	private String url;

	private Pattern pattern = Pattern
			.compile("http://www.douban.com/event/[0-9]*/?");

	Pattern datePattern = Pattern.compile(".*T.*");
	SimpleDateFormat format;

	private String desc;

	private TagsDAO tagsDAO;

	private ActivityTagsDAO activityTagsDAO;

	private static List<String> invalStrings;

	public HTMLInfoExtractor() {
		CleanerProperties properties = new CleanerProperties();
		properties.setCharset("UTF-8");
		properties.setOmitComments(true);
		cleaner = new HtmlCleaner(properties);
		invalStrings = new ArrayList<String>();
		format = new SimpleDateFormat("yyyy-mm-dd HH:MM:SS");
		tagsDAO = new TagsDAO();
		activityTagsDAO = new ActivityTagsDAO();
	}

	public void setCleanerString(String source, String url) {
		rootNode = cleaner.clean(source);
		cleaner.clean(url);
		this.url = url;
	}

	public void extract() {
		if (!pattern.matcher(url).matches() || rootNode == null)
			return;
		ActivityInfo info = new ActivityInfo();
		TagNode activityDetail = getNodeByAttrValue("class", "event-info",
				rootNode);

		// activity pic
		TagNode imageNode = getNodeByAttrValue("class", "poster", rootNode);
		imageNode = imageNode.findElementByName("a", true);
		info.setActivityPic(imageNode.getAttributeByName("href"));

		// activity name
		TagNode nameNode = getNodeByAttrValue("itemprop", "summary",
				activityDetail);
		info.setActivityName(nameNode.getText().toString());

		// activity start & end date
		TagNode timeNode = getNodeByAttrValue("itemprop", "startDate",
				activityDetail);
		info.setActivityStartDate(timeNode.getAttributeByName("datetime")
				.toString());
		timeNode = getNodeByAttrValue("itemprop", "endDate", activityDetail);
		info.setActivityEndDate(timeNode.getAttributeByName("datetime")
				.toString());

		// activity location
		TagNode locationNode = getNodeByAttrValue("itemprop", "location",
				activityDetail);
		info.setActivityLocation(getNodeByAttrValue("itemprop", "region",
				locationNode).getText().toString()
				+ getNodeByAttrValue("itemprop", "locality", locationNode)
						.getText().toString()
				+ getNodeByAttrValue("itemprop", "street-address", locationNode));

		// activity tag
		TagNode tagNode = getNodeByAttrValue("itemprop", "eventType",
				activityDetail);
		info.setActivityTag(tagNode.getText().toString());

		// activity desc
		TagNode tagDesc = getNodeByAttrValue("id", "edesc_f", rootNode);
		info.setActivityDesc(tagDesc.getText().toString());
		try {
			ActivitiesDAO.getInstance().save(cleanInfo(info));
			if (tagsDAO.findByProperty("tagName", info.getActivityTag()) == null)
				tagsDAO.save(new Tags(null, info.getActivityTag()));
			Activity activity = (Activity) ActivitiesDAO.getInstance()
					.findByActivityName(info.getActivityName()).get(0);
			activityTagsDAO.save(new ActivityTags((Tags) tagsDAO.findByTagName(
					info.getActivityTag()).get(0), activity));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private Activity cleanInfo(ActivityInfo info) {
		Activity activity = new Activity();
		if (datePattern.matcher(info.getActivityStartDate()).matches()) {
			info.setActivityStartDate(info.getActivityStartDate().replace("T",
					" "));
		}
		if (datePattern.matcher(info.getActivityEndDate()).matches()) {
			info.setActivityEndDate(info.getActivityEndDate().replace("T", " "));
		}
		try {
			activity.setActivityEndDate(format.parse(info.getActivityEndDate()));
			activity.setActivityStartDate(format.parse(info
					.getActivityStartDate()));
		} catch (ParseException e) {
			// cannot parse date, use currentDate;
			activity.setActivityEndDate(new Date());
			activity.setActivityStartDate(new Date());
			e.printStackTrace();
		}
		// clean those invalid HTML part
		for (String str : invalStrings) {
			info.setActivityDesc(info.getActivityDesc().replaceAll(str, ""));
		}
		if (info.getActivityDesc().length() >= 2000) {
			info.setActivityDesc(info.getActivityDesc().substring(0, 1998));
		}
		activity.setActivityDesc(info.getActivityDesc());

		for (String string : invalStrings) {
			info.setActivityLocation(info.getActivityLocation().replaceAll(
					string, ""));
		}
		activity.setActivityLocation(info.getActivityLocation());

		activity.setActivityName(info.getActivityName());
		activity.setActivityType(0);
		activity.setActivityCreateUserId(1);
		activity.setActivityPic(info.getActivityPic());
		activity.setActivityPublishDate(new Date());
		return activity;
	}

	private TagNode getNodeByAttrValue(String attrName, String attrValues,
			TagNode node) {
		return node.findElementByAttValue(attrName, attrValues, true, true);
	}

}
